#include "..\\pluswindows.mbm.h"


int VIEWx = 600;
int VIEWy = 400;
//#define VIEWx 600
//#define VIEWy 400
//#define VIEWx 800
//#define VIEWy 200
//#define VIEWx 800
//#define VIEWy 400
//#define VIEWx 1000
//#define VIEWy 600

class DRAW_GRAF : public mbm::DRAW
{
    public:
		int idGroup;
		int minWidth;
		int minHeight;
        typedef struct view
        {
            int inicioX;
            int inicioY;
            int fimX;
            int fimY;
            int escala;
        }View;

        View view[3];
        int sinalEntrada[2][100], sinalSistema[2][100], sinalSaida[2][100];
        int idTextBox1, idTextBox2, idComboBox1, idComboBox2;
        int amostrasEnt, amostrasSis, amostrasSaida, margem;

        DRAW_GRAF()
        {
            memset(sinalEntrada, 0, sizeof(sinalEntrada));
            memset(sinalSistema, 0, sizeof(sinalSistema));
            memset(sinalSaida  , 0, sizeof(sinalSaida));

            idTextBox1    = 0;
            idTextBox2    = 0;
            amostrasEnt   = 0;
            amostrasSis   = 0;
            amostrasSaida = 0;
            margem        = 10;

            //Ponto Finfal == Ponto Inicial + N*Pixels
            view[0].inicioX = margem;
            view[0].inicioY = margem;
            view[0].fimX    = (VIEWx / 2) - margem - (margem / 2);
            view[0].fimY    = (VIEWy / 2) - margem - (margem / 2);
            view[0].escala  = 20;
            
			view[1].inicioX = margem;
			view[1].inicioY = (VIEWy / 2) + (margem / 2);
            view[1].fimX    = (VIEWx / 2) - (margem / 2) - margem;
            view[1].fimY    = (VIEWy / 2) - (margem / 2) - margem;
            view[1].escala  = 20;
            
			view[2].inicioX = (VIEWx / 2) + (margem / 2);
            view[2].inicioY = margem;
            view[2].fimX    = (VIEWx / 2) - (margem / 2) - margem;
            view[2].fimY    =  VIEWy      -  margem      - margem;
            view[2].escala  = 20;
        }
        
        void render(mbm::WINDOW* w)
        {
		    //======================== Cria as Views ==========================
            //View1
            this->drawRectangle(view[0].inicioX, view[0].inicioY,
                                view[0].fimX   , view[0].fimY   , 0, 0, 0);

            //View2
            this->drawRectangle(view[1].inicioX, view[1].inicioY,
                                view[1].fimX   , view[1].fimY   , 0, 0, 0);

            //View3
            this->drawRectangle(view[2].inicioX, view[2].inicioY,
                                view[2].fimX   , view[2].fimY   , 0, 0, 0);

            //======================== Cria os Eixos ==========================
            //Eixo x da View1
            this->drawLine(view[0].inicioX + margem, (view[0].fimY / 2) + margem,
                           view[0].fimX            , (view[0].fimY / 2) + margem, 200, 200, 200);
                
            //Eixo y da View1
            this->drawLine((view[0].fimX / 2) + margem, view[0].inicioY + margem,
                           (view[0].fimX / 2) + margem, view[0].fimY            , 200, 200, 200);
                
            //Eixo x  da View2
            this->drawLine(view[1].inicioX + margem, VIEWy - (view[1].fimY / 2) - margem,
                           view[1].fimX            , VIEWy - (view[1].fimY / 2) - margem, 200, 200, 200);
        
            //Eixo y da View2
            this->drawLine((view[1].fimX / 2) + margem, view[1].inicioY + margem,
                           (view[1].fimX / 2) + margem, VIEWy - margem  - margem, 200, 200, 200);
                
            //Eixo x  da View3
            this->drawLine(view[2].inicioX + margem, VIEWy / 2,
                           VIEWx - margem - margem , VIEWy / 2, 200, 200, 200);
        
            //Eixo y da View3
			this->drawLine(VIEWx - (view[2].fimX / 2) - margem, view[2].inicioY + margem,
                           VIEWx - (view[2].fimX / 2) - margem, view[2].fimY            , 200, 200, 200);

			//======================== Cria as Escalas ==========================
            //Escala x da View1
            for(int index = (view[0].fimX / 2) + margem; index >= view[0].inicioX + margem; index-=view[0].escala)
                this->drawLine(index, (view[0].fimY / 2) + margem - 3,
                               index, (view[0].fimY / 2) + margem + 3, 0, 0, 0);
            for(int index = (view[0].fimX / 2) + margem; index <= view[0].fimX; index+=view[0].escala)
                this->drawLine(index, (view[0].fimY / 2) + margem - 3,
                               index, (view[0].fimY / 2) + margem + 3, 0, 0, 0);

            //Escala y da View1
            for(int index = (view[0].fimY / 2) + margem; index >= view[0].inicioY + margem; index-=view[0].escala)
                this->drawLine((view[0].fimX / 2) + margem - 3,  index,
                               (view[0].fimX / 2) + margem + 3,  index, 0, 0, 0);
            for(int index = (view[0].fimY / 2) + margem; index <= view[0].fimY; index+=view[0].escala)
                this->drawLine((view[0].fimX / 2) + margem - 3,  index,
                               (view[0].fimX / 2) + margem + 3,  index, 0, 0, 0);

            //Escala x da View2
            for(int index = (view[1].fimX / 2) + margem; index >= view[1].inicioX + margem; index-=view[1].escala)
                this->drawLine(index, VIEWy - (view[1].fimY / 2) - margem - 3,
                               index, VIEWy - (view[1].fimY / 2) - margem + 3, 0, 0, 0);
            for(int index = (view[1].fimX / 2) + margem; index <= view[1].fimX; index+=view[1].escala)
                this->drawLine(index, VIEWy - (view[1].fimY / 2) - margem - 3,
                               index, VIEWy - (view[1].fimY / 2) - margem + 3, 0, 0, 0);

            //Escala y da View2                
            for(int index = view[1].inicioY + (view[1].inicioY / 2) - margem; index >= view[1].inicioY + margem; index-=view[1].escala)
                this->drawLine((view[1].fimX / 2) + margem - 3,  index,
                               (view[1].fimX / 2) + margem + 3,  index, 0, 0, 0);
            for(int index = view[1].inicioY + (view[1].inicioY / 2) - margem; index <= VIEWy - margem - margem; index+=view[1].escala)
                this->drawLine((view[1].fimX / 2) + margem - 3,  index,
                               (view[1].fimX / 2) + margem + 3,  index, 0, 0, 0);

            //Escala x da View3
            for(int index = VIEWx - (view[2].fimX / 2) - margem; index >= view[2].inicioX + margem; index-=view[2].escala)
                this->drawLine(index, (view[2].fimY / 2) + margem - 3,
                               index, (view[2].fimY / 2) + margem + 3, 0, 0, 0);
            for(int index = VIEWx - (view[2].fimX / 2) - margem; index <= VIEWx - margem - margem; index+=view[2].escala)
                this->drawLine(index, (view[2].fimY / 2) + margem - 3,
                               index, (view[2].fimY / 2) + margem + 3, 0, 0, 0);

            //Escala y da View3                
                for(int index = (view[2].fimY / 2) + margem; index >= view[2].inicioY + margem; index-=view[2].escala)
                    this->drawLine(VIEWx - (view[2].fimX / 2) - margem - 3,  index,
                                   VIEWx - (view[2].fimX / 2) - margem + 3,  index, 0, 0, 0);
                for(int index = (view[2].fimY / 2) + margem; index <= VIEWy - margem - margem; index+=view[2].escala)
                    this->drawLine(VIEWx - (view[2].fimX / 2) - margem - 3,  index,
                                   VIEWx - (view[2].fimX / 2) - margem + 3,  index, 0, 0, 0);

			//======================== Plota os Sinais ==========================
            //Plota Sinal de Entrada
            for(int index = 0; index < amostrasEnt; index++)
            {
                this->drawLine((view[0].fimX / 2) + ( sinalEntrada[0][index] * view[0].escala) + margem, (view[0].fimY / 2) + margem,
                               (view[0].fimX / 2) + ( sinalEntrada[0][index] * view[0].escala) + margem,
                               (view[0].fimY / 2) + (-sinalEntrada[1][index] * view[0].escala) + margem, 0, 0, 255);
                this->drawCircleFilled((view[0].fimX / 2) + ( sinalEntrada[0][index] * view[0].escala) + margem,
                                       (view[0].fimY / 2) + (-sinalEntrada[1][index] * view[0].escala) + margem,  3, 0, 0, 255);
            }

            //Plota Sinal do Sistema
            for(int index = 0; index < amostrasSis; index++)
            {
                this->drawLine((view[1].fimX / 2) + ( sinalSistema[0][index] * view[1].escala) + margem, VIEWy - (view[1].fimY / 2) - margem,
                               (view[1].fimX / 2) + ( sinalSistema[0][index] * view[1].escala) + margem, VIEWy - (view[1].fimY / 2)
							                      + (-sinalSistema[1][index] * view[1].escala) - margem, 255, 0, 0);
                this->drawCircleFilled(        (view[1].fimX / 2) + ( sinalSistema[0][index] * view[1].escala) + margem,
                                       VIEWy - (view[1].fimY / 2) + (-sinalSistema[1][index] * view[1].escala) - margem,  3, 255, 0, 0);
            }


            //Plota Sinal de Saida
            amostrasSaida = amostrasEnt + amostrasSis - 1;
            memset(sinalSaida, 0, sizeof(sinalSaida));
            sinalSaida[0][0] = sinalEntrada[0][0] + sinalSistema[0][0];

            for(int coluna = 0, colunaE = 0, colunaS = 0; coluna < amostrasSaida; coluna++, colunaE = 0, colunaS = coluna)
            {
               sinalSaida[0][coluna + 1] = sinalSaida[0][coluna] + 1;
        
                    //while(colunaS >= 0)
                    //while(colunaE <= coluna && colunaS >= 0)
                    while(colunaE <= coluna)
                        sinalSaida[1][coluna] += sinalEntrada[1][colunaE++] * sinalSistema[1][colunaS--];
                    /*
                    sinalSaida[1][0] = sinalEntrada[1][0] * sinalSistema[1][0];
                    sinalSaida[1][1] = sinalEntrada[1][0] * sinalSistema[1][1] + sinalEntrada[1][1] * sinalSistema[1][0];
                    sinalSaida[1][2] = sinalEntrada[1][0] * sinalSistema[1][2] + sinalEntrada[1][1] * sinalSistema[1][1] + sinalEntrada[1][2] * sinalSistema[1][0];
                    sinalSaida[1][3] = sinalEntrada[1][0] * sinalSistema[1][3] + sinalEntrada[1][1] * sinalSistema[1][2] + sinalEntrada[1][2] * sinalSistema[1][1] + sinalEntrada[1][3] * sinalSistema[1][0];
                    sinalSaida[1][4] = sinalEntrada[1][0] * sinalSistema[1][4] + sinalEntrada[1][1] * sinalSistema[1][3] + sinalEntrada[1][2] * sinalSistema[1][2] + sinalEntrada[1][3] * sinalSistema[1][1] + sinalEntrada[1][4] * sinalSistema[1][0];
                    */
                    this->drawLine(VIEWx - (view[2].fimX / 2) + ( sinalSaida[0][coluna] * view[2].escala) - margem, (view[2].fimY / 2) + margem,
                                   VIEWx - (view[2].fimX / 2) + ( sinalSaida[0][coluna] * view[2].escala) - margem,
                                            view[2].fimY / 2  + (-sinalSaida[1][coluna] * view[2].escala) + margem, 0, 150, 0);
        
                    this->drawCircleFilled(VIEWx - (view[2].fimX / 2) + ( sinalSaida[0][coluna] * view[2].escala) - margem,
                                                    view[2].fimY / 2  + (-sinalSaida[1][coluna] * view[2].escala) + margem, 3, 0, 150, 0);
            }
        }
};


/*
NPP_SAVE
g++ "C:\Users\t178242\pocketcpp\IRAJA\main.cpp" -g
-o "C:\Users\t178242\pocketcpp\IRAJA\graf" -static -std=c++0x 
"C:\Users\t178242\pocketcpp\MinGW\lib\libws2_32.a" 
"C:\Users\t178242\pocketcpp\MinGW\lib\libgdi32.a"  
"C:\Users\t178242\pocketcpp\MinGW\lib\libcomctl32.a" 
"C:\Users\t178242\pocketcpp\MinGW\lib\libcomdlg32.a" -Wall 
*/
void onPressOkEntrada(mbm::WINDOW *w)
{
    char texto[255];
        std::string str;
        std::vector<std::string> results1;
        std::vector<std::string> results2;
        DRAW_GRAF *graf = (DRAW_GRAF *) w->getObjectContext(0);
        memset(graf->sinalEntrada, 0, sizeof(graf->sinalEntrada));
        
        //Montando sinal de entrada
        w->getText(graf->idTextBox1, texto, sizeof(texto));
        mbm::split(results1,texto,':');
        graf->amostrasEnt = results1.size();
        
        for(unsigned int coluna = 0; coluna < results1.size(); coluna++)
        {
            mbm::split(results2,results1[coluna].c_str(), ',');


                if(results2.size() == 2)
                {
                    graf->sinalEntrada[0][coluna] = atoi(results2[0].c_str());
                    graf->sinalEntrada[1][coluna] = atoi(results2[1].c_str());
                }
                results2.clear();
        }
}
void onPressOkSistema(mbm::WINDOW *w)
{
    char texto[255];
        std::vector<std::string> results1;
        std::vector<std::string> results2;
        DRAW_GRAF *graf = (DRAW_GRAF *) w->getObjectContext(0);
        memset(graf->sinalSistema, 0, sizeof(graf->sinalSistema));
        
        //Montando sinal do Sistema
		w->getText(graf->idTextBox2, texto, sizeof(texto));
        mbm::split(results1,texto, ':');
        graf->amostrasSis = results1.size();


        for(unsigned int coluna = 0; coluna < results1.size(); coluna++)
        {
            mbm::split(results2,results1[coluna].c_str(), ',');


                if(results2.size() == 2)
                {
                    graf->sinalSistema[0][coluna] = atoi(results2[0].c_str());
                    graf->sinalSistema[1][coluna] = atoi(results2[1].c_str());
                }
                results2.clear();
        }
        //w->messageBox("OUT");
}


void onPressSpin1(mbm::WINDOW *w, int valor)
{
    DRAW_GRAF *graf = (DRAW_GRAF *) w->getObjectContext(0);
        graf->view[0].escala = valor;
        graf->view[1].escala = valor;
    //w->messageBox("OUT");
}


void onPressSpin2(mbm::WINDOW *w, int valor)
{
    DRAW_GRAF *graf = (DRAW_GRAF *) w->getObjectContext(0);
        graf->view[2].escala = valor;
    //w->messageBox("OUT");
}


void onPressCombobox1(mbm::WINDOW *w)
{
    int valor = 0;
	DRAW_GRAF *graf = (DRAW_GRAF *) w->getObjectContext(0);

	valor = w->getSelectedIndexFromCombobox(graf->idComboBox1);

	if(valor == 0)//Simetria Par
	    w->setText(graf->idTextBox1, "-3,-2:-2,-2:-1,2:0,2:1,2:2,-2:3,-2");
	
    if(valor == 1)//Simetria Impar
        w->setText(graf->idTextBox1, "-3,-2:-2,-2:-1,-2:0,0:1,2:2,2:3,2");

    if(valor == 2)//Impulso Unitario
	    w->setText(graf->idTextBox1, "-3,0:-2,0:-1,0:0,2:1,0:2,0:3,0");

    if(valor == 3)//Funcao Degrau
        w->setText(graf->idTextBox1, "-3,0:-2,0:-1,0:0,1:1,1:2,1:3,1");

	if(valor == 4)//Funcao Sinal
        w->setText(graf->idTextBox1, "-3,-1:-2,-1:-1,-1:0,1:1,1:2,1:3,1");
		
	if(valor == 5)//Retangular
        w->setText(graf->idTextBox1, "-4,0:-3,0:-2,1:-1,1:0,1:1,1:2,1:3,0:4,0");
	
	if(valor == 6)//Seno
        w->setText(graf->idTextBox1, "-6,2:-5,1:-4,-0:-3,-1:-2,-2:-1,-1:0,0:1,1:2,2:3,1:4,0:5,-1:6,-2");
	
	if(valor == 7)//Cosseno
        w->setText(graf->idTextBox1, "-6,-0:-5,-1:-4,-2:-3,-1:-2,0:-1,1:0,2:1,1:2,0:3,-1:4,-2:5,-1:6,0");
}


void onPressCombobox2(mbm::WINDOW *w)
{
    int valor = 0;
	DRAW_GRAF *graf = (DRAW_GRAF *) w->getObjectContext(0);

	valor = w->getSelectedIndexFromCombobox(graf->idComboBox2);

	if(valor == 0)//Simetria Par
	    w->setText(graf->idTextBox2, "-3,-2:-2,-2:-1,2:0,2:1,2:2,-2:3,-2");
	
    if(valor == 1)//Simetria Impar
        w->setText(graf->idTextBox2, "-3,-2:-2,-2:-1,-2:0,0:1,2:2,2:3,2");

    if(valor == 2)//Impulso Unitario
	    w->setText(graf->idTextBox2, "-3,0:-2,0:-1,0:0,2:1,0:2,0:3,0");

    if(valor == 3)//Funcao Degrau
        w->setText(graf->idTextBox2, "-3,0:-2,0:-1,0:0,1:1,1:2,1:3,1");

	if(valor == 4)//Funcao Sinal
        w->setText(graf->idTextBox2, "-3,-1:-2,-1:-1,-1:0,1:1,1:2,1:3,1");
		
	if(valor == 5)//Retangular
        w->setText(graf->idTextBox2, "-4,0:-3,0:-2,1:-1,1:0,1:1,1:2,1:3,0:4,0");
	
	if(valor == 6)//Seno
        w->setText(graf->idTextBox2, "-6,2:-5,1:-4,-0:-3,-1:-2,-2:-1,-1:0,0:1,1:2,2:3,1:4,0:5,-1:6,-2");
	
	if(valor == 7)//Cosseno
        w->setText(graf->idTextBox2, "-6,-0:-5,-1:-4,-2:-3,-1:-2,0:-1,1:0,2:1,1:2,0:3,-1:4,-2:5,-1:6,0");
}


void onChangeWindow(mbm::WINDOW *w,int type)
{
	if(type == mbm::WINPLUS_ON_RESIZE_WINDOW)
	{
		DRAW_GRAF *graf = (DRAW_GRAF *) w->getObjectContext(0);
		VIEWx = w->getWidth();
		VIEWy = w->getHeight();
		if(VIEWx < graf->minWidth || VIEWy < graf->minHeight)
		{
			VIEWx = graf->minWidth;
			VIEWy = graf->minHeight;
		}
		w->resize(graf->idGroup,VIEWx - 20,VIEWy - 80);
	}
	else if(type == mbm::WINPLUS_ON_CLOSE_WINDOW)
	{
		w->run = false;
	}
}

int main(int argv,char** argc)
{
        mbm::WINDOW w;
        DRAW_GRAF graf;
        
        //w.init(600,400,0,0,0,0,1,0,NULL,0,0,0,0,&graf);
        //w.init(800,400);
        //w.init(VIEWx + 200, VIEWy);
		//w.init(0,0,0,0,0,0,0,1);
        w.setNameAplication("Convolucao");
		//VIEWx = w.getWidth()-20;
		//VIEWy = w.getHeight()-20;
        //w.init(VIEWx + 20, VIEWy + 80, 0, 0, 1);
		w.init(VIEWx + 20, VIEWy + 80,0,0,1,1,1,0,onChangeWindow);
		graf.minWidth = VIEWx + 20;
		graf.minHeight= VIEWy + 80;
        //int idgroup = w.addGroupRender(VIEWx, VIEWy);
        graf.idGroup = w.addGroupBox("", 10, 70, VIEWx, VIEWy);
        //int idGroup = w.addGroupBox("Teste", 0, 0, VIEWx, VIEWy);
        w.initDraw(&graf, graf.idGroup);

        w.hideConsoleWindow();
        w.addLabel("Sinal de Entrada", 10, 10, 110, 20, -1);
        w.addLabel("Sinal do Sistema", 10, 40, 110, 20, -1);
        graf.idTextBox1 = w.addTextBox("-6,0:-5,0:-4,0:-3,0:-2,0:-1,0:0,0:1,0:2,0:3,0:4,0:5,0:6,0", 125, 10, VIEWx - 300, 20, -1);
        graf.idTextBox2 = w.addTextBox("-6,0:-5,0:-4,0:-3,0:-2,0:-1,0:0,0:1,0:2,0:3,0:4,0:5,0:6,0", 125, 40, VIEWx - 300, 20, -1);
        graf.idComboBox1 = w.addCombobox(VIEWx - 170, 10, 100, 110, onPressCombobox1);
        graf.idComboBox2 = w.addCombobox(VIEWx - 170, 40, 100, 105, onPressCombobox2);

		w.addStringToCombobox(graf.idComboBox1, "Par");
		w.addStringToCombobox(graf.idComboBox1, "Impar");
		w.addStringToCombobox(graf.idComboBox1, "Unitario");
		w.addStringToCombobox(graf.idComboBox1, "Degrau");
		w.addStringToCombobox(graf.idComboBox1, "Sinal");
		w.addStringToCombobox(graf.idComboBox1, "Retangular");
		w.addStringToCombobox(graf.idComboBox1, "Seno");
		w.addStringToCombobox(graf.idComboBox1, "Cosseno");
		
		w.addStringToCombobox(graf.idComboBox2, "Par");
		w.addStringToCombobox(graf.idComboBox2, "Impar");
		w.addStringToCombobox(graf.idComboBox2, "Unitario");
		w.addStringToCombobox(graf.idComboBox2, "Degrau");
		w.addStringToCombobox(graf.idComboBox2, "Sinal");
		w.addStringToCombobox(graf.idComboBox2, "Retangular");
		w.addStringToCombobox(graf.idComboBox2, "Seno");
		w.addStringToCombobox(graf.idComboBox2, "Cosseno");

        w.addButton("OK", VIEWx - 65, 10, 25, 20, -1, onPressOkEntrada);
        w.addButton("OK", VIEWx - 65, 40, 25, 20, -1, onPressOkSistema);

        w.addSpinInt(VIEWx - 35, 10, 25, 20, -1, 0, 0, onPressSpin1, 2, 30, 5, 20);
        w.addSpinInt(VIEWx - 35, 40, 25, 20, -1, 0, 0, onPressSpin2, 2, 30, 5, 20);
        w.setObjectContext(0, &graf);
        w.enterLoop(NULL);


        return(0);
}